/*
 * timedemo.c
 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <sqlite3.h>
#include <Python.h>

#define N 100
#define NDOCENTES 100000

//Cabeçalhos dos metodos callbacks
static int callBackNumeroDocentes(int *** nrDocentes, int argc, char **argv, char **azColName);
static int callBackNrDocentesEstab(int*** nr, int argc, char **argv, char **azColName);
static int callBackNrDocentesGrau(int*** nr, int argc, char **argv, char **azColName);
static int callBackListaTipEst(char*** lista, int argc, char **argv, char **azColName);
static int callBackListaTitularesGrau(char*** lista, int argc, char **argv, char **azColName);
static int callBackListaEst(char*** lista, int argc, char **argv, char **azColName);
static int callBackcount(int*** nr, int argc, char **argv, char **azColName);
//____________________//_______________________//
//Cabeçalho do metodo escrever no ficheiro
void writeFile(char test[]);

//____________________//_______________________//

/**
 * Metodo callBack do Número de Docentes 
 */
static int callBackNumeroDocentes(int *** nrDocentes, int argc, char **argv, char **azColName){
	**nrDocentes = atoi(argv[0] ? argv[0] : NULL);
	return 0;
}

/**
 * Metodo que lê e processa dos dados de uma base dados
 * através de consultas a Base dados de forma a obter o numero
 * de docentes num determinado ano
 * devolve o numero total de docentes, através de uma variavel do 
 * tipo PyObject*.
 * Recebe como parametro o ano a que se referem o numero de docentes.
 * O metodo também escreve num ficheiro a estatistica.
 */
PyObject* nrTotalDocentesAno(int ano)
{
	PyObject* valor_retorno;
	int** nrDocentes;
	nrDocentes = malloc(sizeof(int));
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	char nrDocentesString[7];
	char anoString[10];
	sprintf(anoString, "%d", ano);
	char tiluloDaEstatistica[100] = "Estatistica do número total de Docentes no ensino superior no ano 200";
	strcat(tiluloDaEstatistica, anoString);
	//strcat(tiluloDaEstatistica, "\n");
	writeFile(tiluloDaEstatistica);
	valor_retorno = PyList_New(N);
	
	//abre a Base Dados (BaseDadosrebides.db) 
	rc = sqlite3_open("BaseDadosrebides.db", &db);
	if( rc ){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		exit(1);
	}
	//Consulta que devolve o numero total de docentes em cada ano
	char queryNrDocentes[80] = "SELECT count(DISTINCT docente) as Docentes from registo_docentes where ano =";
	strcat(queryNrDocentes, anoString);
	rc = sqlite3_exec(db, queryNrDocentes, callBackNumeroDocentes, &nrDocentes, &zErrMsg);
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	//FIM
	//fecha a Base Dados (BaseDadosrebides.db)
	sqlite3_close(db);

	printf("Número total de docentes no ensino superior no ano 200%d = %d\n", ano, *nrDocentes);
	//escrever no ficheiro
	char testoFicheiro[300] = "Número total de docentes no ensino superior no ano 200";
	strcat(testoFicheiro, anoString);
	strcat(testoFicheiro, " é igual a  ");
	sprintf(nrDocentesString,"%d", ((int)*nrDocentes));
	strcat(testoFicheiro, nrDocentesString);
	strcat(testoFicheiro, "\n");
	writeFile(testoFicheiro);
	//FIM escrever no ficheiro
	
	valor_retorno = PyInt_FromLong(*nrDocentes);
	free(nrDocentes);
	return (valor_retorno);
}
//____________________//_______________________//

/**
 * Metodo callback do numero de docentes por estabelecimento
 */
static int callBackNrDocentesEstab(int*** nr, int argc, char **argv, char **azColName){
	**nr = atoi(argv[0] ? argv[0] : NULL);
	return 0;
}

/*
 * Metodo que vai dar a estatistica com o numero total de docentes
 * por tipo de estabelecimento e por ano
 * recebe como parametro o ano
 * Este metodo faz três tipos de consulta a base de dados,
 * a primeira com o número de estabelecimentos num dado ano, a segunda 
 * a lista de estabelecimentos nesse mesmo ano, por fim a terceira 
 * que vai dar contar o numero total de docentes para cada estabelecimento.
 * De referir ainda que este metodo faz a ordenação da lista dos estabelecimentos
 * através da função qsort, que recebes como parametro o nome da lista a ordenar,
 * o numero de elementos da lista, o siseof e a função de comparação, neste caso
 * a função strcmp.
 * O metodo também escreve num ficheiro a estatistica.
 */
int totalNrDocentesEstabAno(int ano)
{	
	int j, i;
	int** nr = malloc(sizeof(int));
	int** nrEstabelecimentos = malloc(sizeof(int));
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	char nrDocentString[10];
	char anoString[10];
	sprintf(anoString, "%d", ano);
	char tiluloDaEstatistica[100] = "Estatistica do número total de Docentes por Estabelecimento no ano 200";
	strcat(tiluloDaEstatistica, anoString);
	strcat(tiluloDaEstatistica, "\n");
	writeFile(tiluloDaEstatistica);
	char** lista;
	char** first;
	lista = (char**) malloc(1000 * sizeof(char*));
	for(j = 0; j < 1000; j++){
		lista[j] = (char*) malloc(200 * sizeof(char));
	}
	first = lista;
	
	//abre a Base Dados (BaseDadosrebides.db) 
	rc = sqlite3_open("BaseDadosrebides.db", &db);
	if( rc ){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		exit(1);
	}

	//Numero de Estabelecimentos num dado ano
	char queryNrEstabelecimentos [100] = "SELECT count(DISTINCT (estabelecimento)) FROM registo_docentes WHERE ano = ";
	strcat(queryNrEstabelecimentos, anoString);
	rc = sqlite3_exec(db, queryNrEstabelecimentos, callBackcount, &nrEstabelecimentos, &zErrMsg);
	if( rc!=SQLITE_OK )
		{
			fprintf(stderr, "SQL error: %s\n", zErrMsg);
			sqlite3_free(zErrMsg);
		}
	//FIM
	
	// Lista de estabelecimentos
	char query[80] = "SELECT DISTINCT (estabelecimento), ano FROM registo_docentes WHERE ano = ";
	strcat(query, anoString);
	rc = sqlite3_exec(db, query, callBackListaEst, &lista, &zErrMsg);
	if( rc!=SQLITE_OK )
		{
			fprintf(stderr, "SQL error: %s\n", zErrMsg);
			sqlite3_free(zErrMsg);
		}
	//ordenação da lista de estabelecimentos
	qsort(lista, (*nrEstabelecimentos), sizeof(char *), strcmp );
	//FIM 

	for(i = 0; i < ((int)(*nrEstabelecimentos)); i++)
	{
		//Número de docentes por estabelecimento, num dado ano
		char estabelecimento[100];
		char andAno [12] = " AND ano = ";
		char queryNrDocentesEstab[250] = "SELECT count(DISTINCT docente) as Docentes from registo_docentes WHERE estabelecimento Like ";
		sprintf(estabelecimento, "'%s'", *first);
		strcat(queryNrDocentesEstab, estabelecimento);
		strcat(queryNrDocentesEstab, andAno);
		sprintf(anoString, "%d", ano);
		strcat(queryNrDocentesEstab, anoString);
		rc = sqlite3_exec(db, queryNrDocentesEstab, callBackNrDocentesEstab, &nr, &zErrMsg);
		if( rc!=SQLITE_OK )
		{
			fprintf(stderr, "SQL error: %s\n", zErrMsg);
			sqlite3_free(zErrMsg);
		}
		//FIM
		
		printf("Número total de docentes no estabelecimento %s no ano 200%d = %d\n\n"
			   		, *first, ano, ((int)*nr));
		//escrever no ficheiro
		char testoFicheiro[300] = "Número total de docentes no estabelecimento  ";
		strcat(testoFicheiro, estabelecimento);
		strcat(testoFicheiro, " no ano 200");
		strcat(testoFicheiro, anoString);
		strcat(testoFicheiro, " é igual a ");
		sprintf(nrDocentString, "%d", ((int)*nr));
		strcat(testoFicheiro, nrDocentString);
		writeFile(testoFicheiro);
		//FIM escrever no ficheiro
		first++;
	}	
	//fecha a Base Dados (BaseDadosrebides.db)
	sqlite3_close(db);
	/*
	for(j = 0; j < 1000; j++){
		free(first[j]);
	}
	free(first);*/
	
	free(nrEstabelecimentos);
	free(nr);	
	return (0);
}

//____________________//_______________________//

/**
 * Metodo callback do total de numero de docentes por grau
 */
static int callBackNrDocentesGrau(int*** nr, int argc, char **argv, char **azColName){
	**nr = atoi(argv[0] ? argv[0] : NULL);
	return 0;
}

/**
 * Metodo que vai dar a estatistica dos docentes por grau,
 * recebe como parametro o ano.
 * Este metodo faz a consulta que devolve o numero total
 * de docentes em cada grau.
 * Importa referir que este metodo só faz a contagem dos numeros de docentes 
 * para os graus Licenciados, Mestres e Doutoures.
 * O metodo também escreve num ficheiro a estatistica.
 */
int totalNrDocentesGrau(int ano)
{	
	int h;
	int** nr = malloc(sizeof(int));
	char nrDocentString[10];
	char anoString[10];
	sprintf(anoString, "%d", ano);
	char tiluloDaEstatistica[100] = "\nEstatistica do número total de Docentes por grau no ano 200";
	strcat(tiluloDaEstatistica, anoString);
	strcat(tiluloDaEstatistica, "\n");
	writeFile(tiluloDaEstatistica);
	char listaGraus [3][20] = {"%licenci%","%mestre%","do%"};
	char listaGrausPrint [3][20] = {"licenciados","mestre","doutores"};
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;

	//abre a Base Dados (BaseDadosrebides.db) 
	rc = sqlite3_open("BaseDadosrebides.db", &db);
	if( rc ){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		exit(1);
	}
	
	for(h = 0; h < 3; h ++)
	{
		//Número total de docentes por grau
		char queryCountDocentesGrau[200] = "SELECT count(DISTINCT docente) as Docentes FROM registo_docentes WHERE grau LIKE ";
		char grauLicenciado[23];
		sprintf(grauLicenciado, "'%s'", listaGraus[h]);
		strcat(queryCountDocentesGrau, grauLicenciado);
		char andAno [12] = " AND ano = ";
		strcat(queryCountDocentesGrau, andAno);
		strcat(queryCountDocentesGrau,anoString);

		rc = sqlite3_exec(db, queryCountDocentesGrau, callBackNrDocentesGrau, &nr, &zErrMsg);
		if( rc!=SQLITE_OK ){
			fprintf(stderr, "SQL error: %s\n", zErrMsg);
			sqlite3_free(zErrMsg);
		}
		//FIM
		printf("Número total de docentes %s no ano 200%d = %d\n", listaGrausPrint[h], ano, ((int)*nr));
		//escrever no ficheiro
		char testoFicheiro[300] = "Número total de docentes ";
		strcat(testoFicheiro, listaGrausPrint[h]);
		strcat(testoFicheiro, " no ano 200");
		strcat(testoFicheiro, anoString);
		strcat(testoFicheiro, " é igual a ");
		sprintf(nrDocentString, "%d", ((int)*nr));
		strcat(testoFicheiro, nrDocentString);
		writeFile(testoFicheiro);
		//FIM escrever no ficheiro
	}
	//fecha a Base Dados (BaseDadosrebides.db)
	sqlite3_close(db);
	free(nr);
	return (0);
}

//____________________//_______________________//

/**
 * Metodo callback count, este metodo callback é utilizado
 * em várias consultas.
 */
static int callBackcount(int*** nr, int argc, char **argv, char **azColName){
	**nr = atoi(argv[0] ? argv[0] : NULL);
	return 0;
}

/*
 * Metodo que vai dar a estatistica com o numero total de docentes
 * por Grau, por Estabelecimento e por ano
 * recebe como parametro o ano
 * Este metodo faz três tipos de consulta a base de dados,
 * a primeira com o número de estabelecimentos num dado ano, a segunda 
 * a lista de estabelecimentos nesse mesmo ano, por fim a terceira 
 * que vai dar contar o numero total de docentes para cada 
 * estabelecimento com um determinado grau.
 * De referir ainda que este metodo faz a ordenação da lista dos estabelecimentos
 * através da função qsort, que recebes como parametro o nome da lista a ordenar,
 * o numero de elementos da lista, o siseof e a função de comparação, neste caso
 * a função strcmp.
 * O metodo também escreve num ficheiro a estatistica.
 */
int totalNrDocentesGrauEst(int ano)
{	
	int j, i, h;
	int** nr = malloc(sizeof(int));
	int** nrEstabelecimentos = malloc(sizeof(int));
	
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	char nrDocentString[10];
	char anoString[10];
	sprintf(anoString, "%d", ano);
	char tiluloDaEstatistica[100] = "\nEstatistica do número total de Docentes por grau e por estabelecimento no ano 200";
	strcat(tiluloDaEstatistica, anoString);
	strcat(tiluloDaEstatistica, "\n");
	writeFile(tiluloDaEstatistica);
	char listaGraus [3][20] = {"%licenci%","%mestre%","do%"};
	char listaGrausPrint [3][20] = {"licenciados","mestre","doutores"};
	char** first;
	char** lista;
	lista = (char**) malloc(1000 * sizeof(char*));

	for(j = 0; j < 1000; j++){
		lista[j] = (char*) malloc(200 * sizeof(char));
	}
	first = lista;

	//abre a Base Dados (BaseDadosrebides.db) 
	rc = sqlite3_open("BaseDadosrebides.db", &db);
	if( rc ){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		exit(1);
	}

	//Numero de Estabelecimentos num dado ano
	char queryNrEstabelecimentos [100] = "SELECT count(DISTINCT (estabelecimento)) FROM registo_docentes WHERE ano = ";
	strcat(queryNrEstabelecimentos, anoString);
	rc = sqlite3_exec(db, queryNrEstabelecimentos, callBackcount, &nrEstabelecimentos, &zErrMsg);
	if( rc!=SQLITE_OK ){
				fprintf(stderr, "SQL error: %s\n", zErrMsg);
				sqlite3_free(zErrMsg);
	}
	//Fim da query do numero de estabelecimentos num dado ano
	
	// Lista de estabelecimentos
	char query[80] = "SELECT DISTINCT (estabelecimento), ano FROM registo_docentes WHERE ano = ";
	strcat(query, anoString);
	rc = sqlite3_exec(db, query, callBackListaEst, &lista, &zErrMsg);
	if( rc!=SQLITE_OK ){
				fprintf(stderr, "SQL error: %s\n", zErrMsg);
				sqlite3_free(zErrMsg);
	}
	//ordenação da lista de estabelecimentos
	qsort(lista, (*nrEstabelecimentos), sizeof(char *), strcmp  );
	//FIM da Lista de Estabelecimentos 

	for(i =0; i < ((int)(*nrEstabelecimentos)); i++)
	{	
		for (h = 0 ; h < 3; h++)
		{
			//Query que calcula o numero total de docentes por grau e 
			//por tipo de estabelecimento e por ano
			char TGrau[23];
			char estabelLike[30] = " AND estabelecimento LIKE ";
			char estabelecimento[100];
			char andAno [12] = " AND ano = ";
			char queryNrDocentes[400] = "SELECT count(DISTINCT docente) as Docentes from registo_docentes WHERE grau LIKE ";
			sprintf(anoString, "%d", ano);
			sprintf(TGrau, "'%s'", listaGraus[h]);
			strcat(queryNrDocentes, TGrau);
			strcat(queryNrDocentes, estabelLike);
			sprintf(estabelecimento, "'%s'", *first);
			strcat(queryNrDocentes,estabelecimento);
			strcat(queryNrDocentes,andAno);
			strcat(queryNrDocentes,anoString);
			rc = sqlite3_exec(db, queryNrDocentes, callBackcount, &nr, &zErrMsg);
			if( rc!=SQLITE_OK ){
				fprintf(stderr, "SQL error: %s\n", zErrMsg);
				sqlite3_free(zErrMsg);
			}
			printf("Número total de docentes com o grau %s, no estabelecimento %s no ano 200%d = %d\n"
			   		, listaGrausPrint[h], *first, ano, ((int)*nr));
			//escrever no ficheiro
			char testoFicheiro[300] = "Número total de docentes com o grau ";
			strcat(testoFicheiro, listaGrausPrint[h]);
			strcat(testoFicheiro, " no estabelecimento ");
			strcat(testoFicheiro, estabelecimento);
			strcat(testoFicheiro, " no ano 200");
			strcat(testoFicheiro, anoString);
			strcat(testoFicheiro, " é igual a ");
			sprintf(nrDocentString, "%d", ((int)*nr));
			strcat(testoFicheiro, nrDocentString);
			writeFile(testoFicheiro);
			//FIM escrever no ficheiro
		}
		first++;
	}
	//fecha a Base Dados (BaseDadosrebides.db)
	sqlite3_close(db);
	
	free(nrEstabelecimentos);
	free(nr);
	return (0);
}

//____________________//_______________________//

/**
 * Metodo callBack da lista dos tipos de estabelecimento 
 */
static int callBackListaTipEst(char*** lista, int argc, char **argv, char **azColName){
	int i;
	for(i=0; i<argc; i++){
		if(i == 0){
			sprintf(**lista, "%s", argv[0]);
			(*lista)++;		
		}
    }
    return 0;
}

/**
 * Metodo que vai dar uma lista com os tipos de estabelecimentos por ano
 * recebe como parametro o ano.
 * Este metodo faz dois tipos de consulta a base de dados,
 * a primeira com o número de instituições num dado ano e a segunda 
 * a lista de instituições nesse mesmo ano.
 * De referir ainda que este metodo faz a ordenação da lista de Instituições
 * através da função qsort, que recebes como parametro o nome da lista a ordenar,
 * o numero de elementos da lista, o siseof e a função de comparação, neste caso
 * a função strcmp.
 * O metodo também escreve num ficheiro a estatistica.
 */
int listaTipoEstab(int ano)
{  
	int i, j;
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	char contString[4];
	char anoString[10];
	sprintf(anoString, "%d", ano);
	char tiluloDaEstatistica[100] = "\nEstatistica lista do tipo de estabelecimentos no ano 200";
	strcat(tiluloDaEstatistica, anoString);
	strcat(tiluloDaEstatistica, "\n");
	writeFile(tiluloDaEstatistica);
	int** nrInstituicoes = malloc(sizeof(int));
	char** first;
	char** lista;
	lista = (char**) malloc(10 * sizeof(char*));

	for(j = 0; j < 10; j++){
		lista[j] = (char*) malloc(100 * sizeof(char));
	}
	first = lista;
	//abre a Base Dados (BaseDadosrebides.db) 
	rc = sqlite3_open("BaseDadosrebides.db", &db);
	if( rc ){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		exit(1);
	}
	//Número de instituições num dado ano
	char queryNrInstituicoes[150] = "SELECT COUNT (DISTINCT (tipo_estabelecimento)) AS Número_Instituições  FROM registo_docentes WHERE ano = ";
	strcat(queryNrInstituicoes, anoString);
	//printf("%s\n", queryNrInstituicoes);
	rc = sqlite3_exec(db, queryNrInstituicoes, callBackcount, &nrInstituicoes, &zErrMsg);
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	//printf("Número de instituiçoes em cada ano %d\n", *nrInstituicoes);
	// FIM

	//lista de instituições num dado ano
	char query[80] = "SELECT DISTINCT (tipo_estabelecimento), ano FROM registo_docentes WHERE ano = ";
	rc = sqlite3_exec(db, strcat(query,anoString), callBackListaTipEst, &lista, &zErrMsg);
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	//fecha a Base Dados (BaseDadosrebides.db)
	sqlite3_close(db);
	//ordenação da lista de Instituições
	qsort(lista, (*nrInstituicoes), sizeof(char *), strcmp  );
	printf("\n");
	for(i =0; i < (*nrInstituicoes); i++){
		printf("%d) Ano 200%d -> Instituição -> %s\n", i, ano, *first);
		//escrever no ficheiro
		char testoFicheiro[300] = "";
		sprintf(contString, "%d", i);
		strcat(testoFicheiro, contString);
		strcat(testoFicheiro, ") ");
		strcat(testoFicheiro, (*first));
		writeFile(testoFicheiro);
		//FIM escrever no ficheiro
		first++;
	}
	free(*lista);
	free(nrInstituicoes);
	return(0);
}

//____________________//_______________________//

/**
 * Metodo callback Lista dos estabelecimentos em cada ano
 */
static int callBackListaEst(char*** lista, int argc, char **argv, char **azColName){
	int i;
	for(i=0; i<argc; i++){
		if(i == 0){
			sprintf(**lista, "%s", argv[0]);
			(*lista)++;
		}
    }
    return 0;
}

/**
 * Metodo que vai dar a lista dos estabelecimentos num dado ano,
 * recebe como parametro o ano
 * Este metodo faz dois tipos de consulta a base de dados,
 * a primeira com o número de estabelecimentos num dado ano e a segunda 
 * a lista de estabelecimentos nesse mesmo ano.
 * De referir ainda que este metodo faz a ordenação da lista dos estabelecimentos
 * através da função qsort, que recebes como parametro o nome da lista a ordenar,
 * o numero de elementos da lista, o siseof e a função de comparação, neste caso
 * a função strcmp.
 * O metodo também escreve num ficheiro a estatistica
 */
int listaEstab(int ano)
{	
	int i, j;
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	char contString[4];
	char anoString[10];
	sprintf(anoString, "%d", ano);
	char tiluloDaEstatistica[100] = "\nEstatistica lista de estabelecimentos no ano 200";
	strcat(tiluloDaEstatistica, anoString);
	strcat(tiluloDaEstatistica, "\n");
	writeFile(tiluloDaEstatistica);
	char** first;
	char** lista;
	int** nrEstabelecimentos = malloc(sizeof(int));
	lista = (char**) malloc(1000* sizeof(char*));

	for(j = 0; j < 1000; j++){
		lista[j] = (char*) malloc(100 * sizeof(char));
	}
	first = lista;

	//abre a Base Dados (BaseDadosrebides.db) 
	rc = sqlite3_open("BaseDadosrebides.db", &db);
	if( rc ){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		exit(1);
	}
	//Numero de Estabelecimentos num dado ano
	char queryNrEstabelecimentos [100] = "SELECT count(DISTINCT (estabelecimento)) FROM registo_docentes WHERE ano = ";
	strcat(queryNrEstabelecimentos, anoString);
	rc = sqlite3_exec(db, queryNrEstabelecimentos, callBackcount, &nrEstabelecimentos, &zErrMsg);
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	//FIM

	//Lista de estabelecimentos num dado ano
	char query[80] = "SELECT DISTINCT (estabelecimento), ano FROM registo_docentes WHERE ano = ";
	strcat(query,anoString);
	rc = sqlite3_exec(db, query, callBackListaEst, &lista, &zErrMsg);
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	//FIM
	//fecha a Base Dados (BaseDadosrebides.db)
	sqlite3_close(db);

	//ordenação da lista de estabelecimentos
	qsort(lista, (*nrEstabelecimentos), sizeof(char *), strcmp);
	printf("\n");
	for(i =0; i < ((int)(*nrEstabelecimentos)); i++){
		printf("%d) Ano 200%d -> Estabelecimento -> %s\n",i, ano, *first);
		//escrever no ficheiro
		char testoFicheiro[300] = "";
		sprintf(contString, "%d", i);
		strcat(testoFicheiro, contString);
		strcat(testoFicheiro, ") ");
		strcat(testoFicheiro, (*first));
		writeFile(testoFicheiro);
		//FIM escrever no ficheiro
		first++;
	}
	
	free(*lista);
	free(nrEstabelecimentos);
	return(0);
}

//____________________//_______________________//

/**
 * Metodo Callback da Lista dos titulares de cada grau
 */
static int callBackListaTitularesGrau(char*** lista, int argc, char **argv, char **azColName){
	int i;
	for(i=0; i<argc; i++){
		if(i == 0){
			//printf("%s\n", argv[0]);
			sprintf(**lista, "%s", argv[0]);
			
			(*lista)++;		
		}
    }
    return 0;
}

/**
 * Metodo que vai dar a lista dos titulares dos 
 * graus (Licenciados, Mestres e doutores) num dado ano,
 * recebe como parametro o ano
 * Este metodo faz dois tipos de consulta a base de dados,
 * a primeira com o número de docentes por grau num dado ano e a segunda 
 * a lista de docentes dos titulares dos graus nesse mesmo ano.
 * De referir ainda que este metodo faz a ordenação da lista dos titulares dos graus
 * através da função qsort, que recebes como parametro o nome da lista a ordenar,
 * o numero de elementos da lista, o siseof e a função de comparação, neste caso
 * a função strcmp.
 * O metodo também escreve num ficheiro a estatistica.
 * Importa ainda referir que este metodo só faz a contagem e a lista
 * dos docentes com os seguintes graus Licenciados, Mestres e Doutoures.
 */
int listaTitularesGrau(int ano)
{
	int i, j, h;
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	char contString[4];
	char anoString[10];
	sprintf(anoString, "%d", ano);
	char tiluloDaEstatistica[100] = "Estatistica Lista dos Titulares dos graus no ano 200";
	strcat(tiluloDaEstatistica, anoString);
	strcat(tiluloDaEstatistica, "\n");
	writeFile(tiluloDaEstatistica);
	char** first;
	char** lista;
	int** nrDocentesG;
	nrDocentesG = malloc(sizeof(int));

	char listaGraus [3][20] = {"%licenci%","%mestre%","do%"};
	char listaGrausPrint [3][20] = {"licenciado","mestre","doutor"};

	lista = (char**) malloc(NDOCENTES * sizeof(char*));

	for(j = 0; j < NDOCENTES; j++){
		lista[j] = (char*) malloc(300 * sizeof(char));
	}

	first = lista;

	//abre a Base Dados (BaseDadosrebides.db) 
	rc = sqlite3_open("BaseDadosrebides.db", &db);
	if( rc ){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		exit(1);
	}
	for(h = 0; h < 3; h ++)
	{
		//query que conta o numero de docentes por grau
		char queryCountNrDocentGrau[200] = "SELECT count(DISTINCT docente) as Docentes FROM registo_docentes WHERE grau LIKE ";
		char grauLicenciado[23];
		char andAno [12] = " AND ano = ";
		sprintf(grauLicenciado, "'%s'", listaGraus[h]);
		strcat(queryCountNrDocentGrau, grauLicenciado);
		strcat(queryCountNrDocentGrau, andAno);
		strcat(queryCountNrDocentGrau,anoString);
		//printf("%s\n", queryCountNrDocentGrau);
		rc = sqlite3_exec(db, queryCountNrDocentGrau, callBackNumeroDocentes, &nrDocentesG, &zErrMsg);
		if( rc!=SQLITE_OK ){
			fprintf(stderr, "SQL error: %s\n", zErrMsg);
			sqlite3_free(zErrMsg);
		}
		//FIM

		//printf("docentes %d\n", *nrDocentesG);
		lista = first;
		char TGrau[23];
		char queryListaTitularesGraus[250] = "SELECT DISTINCT (docente) as Docentes FROM registo_docentes WHERE grau LIKE ";
		sprintf(anoString, "%d", ano);
		sprintf(TGrau, "'%s'", listaGraus[h]);
		strcat(queryListaTitularesGraus, TGrau);
		strcat(queryListaTitularesGraus,andAno);
		strcat(queryListaTitularesGraus,anoString);
		rc = sqlite3_exec(db, queryListaTitularesGraus, callBackListaTitularesGrau, &lista, &zErrMsg);
		if( rc!=SQLITE_OK ){
			fprintf(stderr, "SQL error: %s\n", zErrMsg);
			sqlite3_free(zErrMsg);
		}
		//ordenação da lista dos titulares dos graus
		qsort(lista, (*nrDocentesG), sizeof(char *), strcmp  );
		printf("\n");
		for(i =0; i < ((int)(*nrDocentesG)) ; i++){
			printf("%d) Ano 200%d -> docente %s -> grau %s\n", i, ano,
			   		*first, listaGrausPrint[h]);
			//escrever no ficheiro
			char testoFicheiro[300] = "";
			sprintf(contString, "%d", i);
			strcat(testoFicheiro, contString);
			strcat(testoFicheiro, ") ");
			strcat(testoFicheiro, (*first));
			strcat(testoFicheiro, " - ");
			strcat(testoFicheiro, listaGrausPrint[h]);
			writeFile(testoFicheiro);
			//FIM escrever no ficheiro
			first++;
		}
	}
	//fecha a Base Dados (BaseDadosrebides.db)
		sqlite3_close(db);
	
	/*for(j=0; j < NDOCENTES; j++){
		free(first[j]);
	}*/
	//free(first);
	free(nrDocentesG);
	return(0);
}

//____________________//_______________________//

/**
 * Metodo que vai dar o numero de docentes que entraram e sairam de 
 * uma instituição de uns anos para os outros.
 * Este metodo faz três tipos de consulta a base de dados,
 * a primeira com o número de Instituições em cada ano,
 * a segunda a lista de Instituições em cada ano e por fim a terceira
 * o número de docentes por instituição em cada ano.
 * De referir ainda que este metodo faz a ordenação da lista das instituições
 * através da função qsort, que recebes como parametro o nome da lista a ordenar,
 * o numero de elementos da lista, o siseof e a função de comparação, neste caso
 * a função strcmp.
 * O metodo também escreve num ficheiro a estatistica.
 * o Metodo faz a comparação do numero de docentes em cada instituição de uns anos 
 * para os outros.
 */ 
int NrDocentesSairamEntraramInstituicao()
{
	int i, j, ano;
	int contador = 0;
	char contadorString[4];
	int nrDocentesInsti;
	char nrDocentesInsString[6];
	char nomeInstituicao[100];
	char tiluloDaEstatistica[100] = "Estatistica do número de Entradas e Saidas em cada estabelecimento por ano\n";
	writeFile(tiluloDaEstatistica);
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	char** first;
	char** lista;
	int** nrDocentes = malloc(sizeof(int));
	int** nrInstituicoes = malloc(sizeof(int));
	
	lista = (char**) malloc(NDOCENTES * sizeof(char*));

	for(j = 0; j < NDOCENTES; j++){
		lista[j] = (char*) malloc(300 * sizeof(char));
	}
	first = lista;

	//abre a Base Dados (BaseDadosrebides.db) 
	rc = sqlite3_open("BaseDadosrebides.db", &db);
	if( rc ){
		fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
		sqlite3_close(db);
		exit(1);
	}
	for(i = 0; i < 5; i++)
	{
		//percorrer os os anos de 2000 a 2009
		for (ano = 0; ano < 10; ano ++)
		{
			//Número de instituições em cada ano
			char anoString[4];
			char queryNrInstituicoes[150] = "SELECT COUNT (DISTINCT (tipo_estabelecimento)) AS Número_Instituições  FROM registo_docentes WHERE ano = ";
			sprintf(anoString,"%d", ano);
			strcat(queryNrInstituicoes, anoString);
			//printf("%s\n", queryNrInstituicoes);
			rc = sqlite3_exec(db, queryNrInstituicoes, callBackcount, &nrInstituicoes, &zErrMsg);
			if( rc!=SQLITE_OK ){
				fprintf(stderr, "SQL error: %s\n", zErrMsg);
				sqlite3_free(zErrMsg);
			}
			//printf("Número de instituiçoes em cada ano %d\n", *nrInstituicoes);
			// FIM

			//Lista da instituições em cada ano
			char queryListaInstitucoes[150] = "SELECT DISTINCT (tipo_estabelecimento) AS Instituições FROM registo_docentes WHERE ano = ";
			strcat(queryListaInstitucoes, anoString);
			//printf("%s\n", queryListaInstitucoes);
			rc = sqlite3_exec(db, queryListaInstitucoes, callBackListaTipEst, &lista, &zErrMsg);
			if( rc!=SQLITE_OK ){
				fprintf(stderr, "SQL error: %s\n", zErrMsg);
				sqlite3_free(zErrMsg);
			}
			//FIM
			//ordenação da lista de instituições	
			qsort(lista, (*nrInstituicoes), sizeof(char *), strcmp  );
			

			//Número de docentes por instituição em cada ano
			char instituicao[100];
			char andAno [12] = " AND ano = ";
			char queryNrDocentesInst[250] = "SELECT COUNT (DISTINCT (docente)) AS docentes  FROM registo_docentes WHERE tipo_estabelecimento LIKE ";
			sprintf(instituicao, "'%s'", *first);
			strcat(queryNrDocentesInst, instituicao);
			strcat(queryNrDocentesInst, andAno);
			strcat(queryNrDocentesInst, anoString);
			rc = sqlite3_exec(db, queryNrDocentesInst, callBackcount, &nrDocentes, &zErrMsg);
			if( rc!=SQLITE_OK ){
				fprintf(stderr, "SQL error: %s\n", zErrMsg);
				sqlite3_free(zErrMsg);
			}
			//printf("Numero docentes no estab %s no ano 200%d = %d\n", *first, ano, *nrDocentes);
			//FIM

			if(ano == 0)
			{
				nrDocentesInsti = ((int)*nrDocentes);
				sprintf(nrDocentesInsString,"%d", nrDocentesInsti);
				sprintf(nomeInstituicao, "%s", *first);
				printf("\nNo ano 200%d o número de docentes na instituição %s é = %d\n\n",
				       ano, nomeInstituicao, nrDocentesInsti);

				//escrever no ficheiro
				char testoFicheiro[300] = "No ano 200";
				strcat(testoFicheiro, anoString);
				strcat(testoFicheiro, " o número de docentes na instituição ");
				strcat(testoFicheiro, nomeInstituicao);
				strcat(testoFicheiro, " é igual a ");
				strcat(testoFicheiro, nrDocentesInsString);
				writeFile(testoFicheiro);
				//FIM escrever no ficheiro
				contador = 0;
				contador++;
			}
			if(ano == contador)
			{
				if(nrDocentesInsti > (*nrDocentes) 
					 && (strcmp(nomeInstituicao, (*first)) == 0))
				{
					nrDocentesInsti = (nrDocentesInsti) - (int)(*nrDocentes);
					printf("Do ano 200%d para o ano 200%d -> Sairam da instituição %s, %d docentes\n",
					       (contador - 1), contador, *first, nrDocentesInsti);
					//escrever no ficheiro
					char testoFicheiro[300] = "Do ano 200";
					sprintf(contadorString,"%d", (contador - 1));
					strcat(testoFicheiro, contadorString);
					strcat(testoFicheiro, " para o ano 200");
					sprintf(contadorString,"%d", contador);
					strcat(testoFicheiro, contadorString);
					strcat(testoFicheiro, " Sairam da instituição ");
					strcat(testoFicheiro, nomeInstituicao);
					sprintf(nrDocentesInsString,"%d", nrDocentesInsti);
					strcat(testoFicheiro, nrDocentesInsString);
					strcat(testoFicheiro, " docentes");
					writeFile(testoFicheiro);
					//FIM escrever no ficheiro
					nrDocentesInsti = ((int)*nrDocentes);
					sprintf(nomeInstituicao, "%s", *first);
					contador++;
				}else if(nrDocentesInsti < (*nrDocentes) 
				 	  && (strcmp(nomeInstituicao, (*first)) == 0))
				{
					nrDocentesInsti = (int)(*nrDocentes) - (nrDocentesInsti);
					printf("Do ano 200%d para o ano 200%d -> Entraram na instituição %s, %d docentes\n",
					       (contador - 1), contador, *first, nrDocentesInsti);
					//escrever no ficheiro
					char testoFicheiro[300] = "Do ano 200";
					sprintf(contadorString,"%d", (contador - 1));
					strcat(testoFicheiro, contadorString);
					strcat(testoFicheiro, " para o ano 200");
					sprintf(contadorString,"%d", contador);
					strcat(testoFicheiro, contadorString);
					strcat(testoFicheiro, " Entraram na instituição ");
					strcat(testoFicheiro, nomeInstituicao);
					sprintf(nrDocentesInsString,"%d", nrDocentesInsti);
					strcat(testoFicheiro, " ");
					strcat(testoFicheiro, nrDocentesInsString);
					strcat(testoFicheiro, " docentes");
					writeFile(testoFicheiro);
					//FIM escrever no ficheiro
					nrDocentesInsti = ((int)*nrDocentes);
					sprintf(nomeInstituicao, "%s", *first);
					contador++;
				}else if(nrDocentesInsti == 0 
				      && (strcmp(nomeInstituicao, (*first)) == 0))
				{
					printf("A Instituição %s fechou no ano 200%d\n",
					       nomeInstituicao, (contador - 1));
					//escrever no ficheiro
					char testoFicheiro[300] = "A Instituição ";
					strcat(testoFicheiro, nomeInstituicao);
					strcat(testoFicheiro, " fechou no ano 200");
					sprintf(contadorString,"%d", (contador - 1));
					strcat(testoFicheiro, contadorString);
					writeFile(testoFicheiro);
					//FIM escrever no ficheiro
					nrDocentesInsti = ((int)*nrDocentes);
					sprintf(nomeInstituicao, "%s", *first);
					contador++;
				}		
			}
		}
		first++;
	}
	//fecha a Base Dados (BaseDadosrebides.db)
	sqlite3_close(db);
	
	free(nrDocentes);
	free(nrInstituicoes);
	return(0);
}

//____________________//_______________________//

/**
 * Metodo para escrever as estatisticas e 
 * as listas num ficheiro com o nome
 * file.doc
 * Recebe como parametro a mensagem
 * a escrever no ficheiro.
 * Importa referir que cada vez que este metodo 
 * é chamado é feito um append ao ficheiro, 
 * "file = fopen("file.txt","a+");"
 */
void writeFile(char mensagem[])
{
	FILE *file; 
	file = fopen("file.txt","a+");		
	fprintf(file, "%s", mensagem);
	fprintf(file, "%s", "\n");
	fclose(file);
}


int main(){
	int ano = 0;
	nrTotalDocentesAno(ano);
	totalNrDocentesEstabAno(ano);
	totalNrDocentesGrau(ano);
	totalNrDocentesGrauEst(ano);
	listaTipoEstab(ano);
	listaEstab(ano);
	listaTitularesGrau(ano);
	NrDocentesSairamEntraramInstituicao();
	exit(0);
}